/*
ONEGAME
Copyright (C) 2009  Pablo Caballero

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package one.dialog;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Field editable
 * @author Pablo Caballero
 * @version 1.0 24-jun-2009
 */
public class FieldEditor {

	protected String getname;
	protected String setname;
	protected Object element;
	protected String label;
	protected Method methodget;
	protected Method methodset;
	protected String helpTitle;
	protected String helpDescription;

	/** Constructor */
	public FieldEditor() {
		this("", "", null, "", "", "");
	}

	/**
	 * Constructor
	 * @param getname the name of the getting function
	 * @param setname the name of the setting function
	 * @param element the element with the given functions
	 * @param label the label of the field
	 */
	public FieldEditor(String getname, String setname, Object element, String label) {
		this(getname, setname, element, label, "", "");
	}

	/**
	 * Constructor
	 * @param getname the name of the getting function
	 * @param setname the name of the setting function
	 * @param element the element with the given functions
	 * @param label the label of the field
	 * @param helpTitle the title for the help section
	 * @param helpDescription the description for the help section
	 */
	public FieldEditor(String getname, String setname, Object element, String label, String helpTitle, String helpDescription) {
		setGetname(getname);
		setSetname(setname);
		setElement(element);
		setLabel(label);
		setHelpTitle(helpTitle);
		setHelpDescription(helpDescription);
	}

	/**
	 * Get the value of getname
	 * @return the value of getname
	 */
	public String getGetname() {
		return getname;
	}

	/**
	 * Set the value of getname
	 * @param getname new value of getname
	 */
	public void setGetname(String getname) {
		this.getname = getname;
		methodget = null;
	}

	/**
	 * Get the value of setname
	 * @return the value of setname
	 */
	public String getSetname() {
		return setname;
	}

	/**
	 * Set the value of setname
	 * @param setname new value of setname
	 */
	public void setSetname(String setname) {
		this.setname = setname;
		methodset = null;
	}

	/**
	 * Get the value of element
	 * @return the value of element
	 */
	public Object getElement() {
		return element;
	}

	/**
	 * Set the value of element
	 * @param element new value of element
	 */
	public void setElement(Object element) {
		this.element = element;
	}

	/**
	 * Get the value of label
	 * @return the value of label
	 */
	public String getLabel() {
		return label;
	}

	/**
	 * Set the value of label
	 * @param label new value of label
	 */
	public void setLabel(String label) {
		this.label = label;
	}

	/**
	 * Find a method in the internal object
	 * @param name
	 * @return
	 */
	protected Method findMethod(String name) {
		Method[] methods = null;
		boolean found = false;
		int i = 0;

		if (element != null) {
			methods = element.getClass().getDeclaredMethods();
			while (i < methods.length && !found) {
				if (methods[i].getName().equals(name)) {
					found = true;
				} else {
					i++;
				}
			}
		}

		return (found ? methods[i] : null);
	}

	public boolean isEditable() {
		if (methodset == null) {
			methodset = findMethod(getSetname());
		}
		return methodset != null;
	}

	/**
	 * Indicates if the get method is available
	 * @return {@code true} if the get method is available
	 */
	public boolean isReadable() {
		if (methodget == null) {
			methodget = findMethod(getGetname());
		}
		return methodget != null;
	}

	/**
	 * Gets the value of the element
	 * @return the value of the element
	 */
	public Object getValue() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NullPointerException, ExceptionInInitializerError {
		if (methodget == null) {
			methodget = findMethod(getGetname());
		}

		if (methodget == null) {
			throw new IllegalAccessException("Method \"" + getGetname() + "\" don't exist.");
		} else {
			return methodget.invoke(getElement());
		}
	}

	/**
	 * Sets the value of the element
	 * @param value The parameter to be saved
	 */
	public void setValue(Object value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NullPointerException, ExceptionInInitializerError {
		if (methodset == null) {
			methodset = findMethod(getSetname());
		}

		if (methodset == null) {
			throw new IllegalAccessException("Method \"" + getGetname() + "\" don't exist.");
		} else {
			methodset.invoke(getElement(), value);
		}
	}

	/**
	 * Get the value of the title of help section
	 * @return the value of helpTitle
	 */
	public String getHelpTitle() {
		return helpTitle;
	}

	/**
	 * Set the value of the title of help section
	 * @param helpTitle new value of helpTitle
	 */
	public void setHelpTitle(String helpTitle) {
		this.helpTitle = helpTitle;
	}

	/**
	 * Get the value of the description of help section
	 * @return the value of helpDescription
	 */
	public String getHelpDescription() {
		return helpDescription;
	}

	/**
	 * Set the value of the description of help section
	 * @param helpDescription new value of helpDescription
	 */
	public void setHelpDescription(String helpDescription) {
		this.helpDescription = helpDescription;
	}
}
